package cn.wizzer.framework.util.param;

import org.nutz.lang.Strings;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Parameter;
import java.lang.reflect.Proxy;
import java.util.Map;
import java.util.Set;
import java.util.regex.Pattern;

/**
 * 验证器
 */
public class ParamValidation {


    public void validation(Map<Parameter, Object> parameterObjectMap) {
        Set<Parameter> parameters = parameterObjectMap.keySet();
        if (parameters.size() > 0) {
            for (Parameter parameter : parameters) {
                Param4MapVerify param4MapVerify = parameter.getAnnotation(Param4MapVerify.class);
                Object value = parameterObjectMap.get(parameter);
                if (param4MapVerify != null) {
                    if (param4MapVerify.fields().length > 0) {
                        Map mapValue = (Map) value;
                        for (ParamVerify paramVerify : param4MapVerify.fields()) {
                            String name = paramVerify.name();
                            if (name.equals("")) {
                                ParamVerifyException.throwNew("the property named 'name' of annotation param in param4map must been not null");
                            }
                            validation(paramVerify, name, mapValue.get(name));
                        }
                    }
                }

                ParamVerify paramVerify = parameter.getAnnotation(ParamVerify.class);
                if (paramVerify != null) {
                    validation(paramVerify, parameter.getName(), value);
                }
            }
        }


    }

    private void setParamName(ParamVerify paramVerify, String name) {
        try {
            // 获取代理处理器
            InvocationHandler invocationHandler = Proxy.getInvocationHandler(paramVerify);
            // 过去私有 memberValues 属性
            Field f = invocationHandler.getClass().getDeclaredField("memberValues");
            f.setAccessible(true);
            // 获取实例的属性map
            Map<String, Object> memberValues = (Map<String, Object>) f.get(invocationHandler);
            // 修改属性值
            memberValues.put("name", name);
        } catch (Exception e) {
        }
    }

    public void validation(ParamVerify paramVerify, String paramName, Object value) {
        if (Strings.isBlank(paramVerify.name())) {
            setParamName(paramVerify, paramName);
        }
        String dft = paramVerify.dft();
        if (value == null) {
            //todo value == dft;req.setParam(paramName,dft)
        }
        boolean required = paramVerify.required();
        if (required) {
            if (value == null) {
                ParamVerifyException.throwNew(String.format("the param named '%s' can not been null", paramVerify.name()));
            }
        }
        String regex = paramVerify.regex();
        if (Strings.isNotBlank(regex)) {
            if (value != null) {
                boolean matches = Pattern.matches(regex, value.toString());
                if (!matches) {
                    ParamVerifyException.throwNew(String.format("the param named '%s' must match '%s'", paramVerify.name(), regex));
                }
            }
        }
        //todo more validate
    }

}
